iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 17
1
Mobile Development

新手試試用Flutter做Netflix UI系列 第 17

[Day17]Flutter Netflix UI 編輯使用者頁面

  • 分享至 

  • xImage
  •  

大家好,今天使用到的有TextEditingController、TextField、InputDecoration、CircularProgressIndicator、AlwaysStoppedAnimation,也會用到先前介紹的Ink、InkWell

CircularProgressIndicator and LinearProgressIndicator (Flutter Widget of the Week)
3.7 输入框及表单

頭像、Ink、InkWell

我們要給圖片加上波紋的特效,找到Ink裡面有一個直接使用圖片背景方法,Ink.image
但是因為沒找到給他做圓角的方法,所以還是用先前用的方法,

//源碼註解說,假如圖片上不會在渲染東西,如沒有波紋的話,推薦使用Container、BoxDecoration
 Ink.image()
 _buildUserAvatar() {
   return Stack(
     children: [
       Padding(
         padding: const EdgeInsets.all(8.0),
         child: Ink(
           decoration: BoxDecoration(
               borderRadius: BorderRadius.circular(8.0), //Ink圓角
               image: DecorationImage(
                 image: AssetImage(
                   widget.user.assetName,
                 ),
               )),
           width: screenSized.width * 0.3,
           height: screenSized.width * .3,
           child: InkWell(
             borderRadius: BorderRadius.circular(8.0),//InkWell 波紋圓角
             onTap: () {},
           ),
         ),
       ),
       Positioned(
         right: 0.0,
         bottom: 0.0,
         child: Icon(Icons.edit),
       )
     ],
   );
 }

TextField文字輸入框、InputDecoration

文字輸入用Container幫輸入框做灰底背景,
使用TextField時可以用InputDecoration,他可以設置輸入框的外觀,提示文字、背景、邊框、錯誤提示等等

 const InputDecoration({
    this.icon,
    this.labelText,
    this.labelStyle,
    this.helperText,
    this.helperStyle,
    this.helperMaxLines,
    this.hintText,
    this.hintStyle,
    this.hintMaxLines,
    this.errorText,
    this.errorStyle,
    this.errorMaxLines,
    @Deprecated(
      'Use floatingLabelBehavior instead. '
      'This feature was deprecated after v1.13.2.'
    )

這邊要設置的是border邊框,InputBorder.none無邊框
TextField設置cursorColor,輸入框光標的顏色

 _buildInputTextField() {
    return Container(
      margin: EdgeInsets.all(16.0),
      padding: EdgeInsets.symmetric(horizontal: 16.0),
      color: Color(0xff333333),
      width: screenSized.width * 0.7,
      child: TextField(
        controller: _editingController,
        cursorColor: Colors.white,
        style: inputStyle,
        decoration:
            InputDecoration(border: InputBorder.none),
      ),
    );
  }

TextEditingController 設置初始文字

設置初始文字或要監聽文字的改變,使用controller
initState實例controller的時候帶入初始文本從前面傳進來的文字

 @override
  void initState() {
    _editingController = TextEditingController(text: widget.user.name);
    _editingController.addListener(() {
      print(_editingController.text);
    });
    super.initState();
  }

FlatButton 儲存按鍵

 /// Create a simple text button.

右上方有一個儲存按鍵,被點擊的時候會變另一種顏色,所以我們可以使用FlatButton
大部分的Button都可以設定好幾種狀態的顏色,例如:highlightColor、hoverColor、splashColor
這邊我們要設的是disabledTextColor、textColor

FlatButton判斷是不是disabled,主要是看onPressed是不是帶null,所以一開始設一個boolean判斷現在是否可以點擊

  bool _isButtonDisabled = false;
FlatButton(
    textColor: saveStyle.color,
    disabledTextColor: Colors.grey,
    padding: EdgeInsets.zero,//預設有padding,所以用`EdgeInsets.zero`
    child: Text("儲存",),
    onPressed: _isButtonDisabled ? null : _saveChange,
 ),

點擊執行_saveChange
更新user.name
變更狀態,並setState
兩秒後返回前一頁

void _saveChange() {
    widget.user.name = _editingController.text;
    print("widget.user.name ${widget.user.name}");
    savingState = true; //用在offstage顯示Loading的動畫
    setState(() {});
    //假設這邊跟雲端聯繫,要顯示Loading,兩秒後,返回結果,回前一頁
    Future.delayed(Duration(seconds: 2), () {
      savingState = false;
      setState(() {
        Navigator.of(context).pop(1);
      });
    });
  }

CircularProgressIndicator、Offstage

Offstage用法在前一篇說過,當savingState為真時,顯示動畫,否則隱藏

CircularProgressIndicator,什麼都不設置就是一個轉圈圈的動畫,
當然也可以設定value,backgroundColor什麼的,這邊只想改變它的顏色valueColor
Animation<Color>需要輸入Animation給它
如果不想顏色變來變去時直接使用AlwaysStoppedAnimation<Color>(color)

 Offstage(
            offstage: !savingState,
            child: Container(
              color: Colors.black.withOpacity(0.5),
              child: Center(
                child: SizedBox(
                  width: 50.0,
                  height: 50.0,
                  child: CircularProgressIndicator(
                    valueColor: AlwaysStoppedAnimation(Colors.red),
                  ),
                ),
              ),
            ),
          )

最後在更新前一頁畫面即可,在前一頁選擇使用者頁面,推進頁面的地方加上.then((value){})

  Navigator.of(context).push(...略過部分code...).then((value){});

value是按返回時傳回來的值,判斷值是否等於1,是的話就更新畫面

 onTap: () {
         //這是在選這使用者頁面,前一篇的
        Navigator.of(context).push(MaterialPageRoute( 
        builder: (_) => editMode? EditUserPage(user: user,): MainPage()))
            .then((value) {
          if (value == 1) {
            setState(() {});
          } else {
            print("未儲存變更");
          }
        });
      },

今日之效果圖
Day17

GitHub連結: flutter-netflix-clone


上一篇
[Day16]Flutter Netflix UI 選擇使用者頁面
下一篇
[Day18]Flutter Netflix UI 更多頁面 Flexible
系列文
新手試試用Flutter做Netflix UI30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言